library(tidyverse)
library(janitor)
library(tsibble)
library(lubridate)
library(ggthemes)
library(tidyverse)
library(sf)
library(rnaturalearth)
library(jsonlite)
library(leaflet)
library(janitor)
library(sp)
wait_times <- read_csv("../Dashboard_project/raw_data/wait_times_data/monthly_ae_waitingtimes_202209.csv") %>% clean_names()
clean_wait_times <- wait_times %>%
select(-c(number_of_attendances_episode_qf, number_meeting_target_episode_qf,
discharge_destination_admission_to_same_qf, discharge_destination_other_specialty_qf,
discharge_destination_residence_qf, discharge_destination_unknown_qf,
discharge_destination_transfer_qf, attendance_greater8hrs_qf,
attendance_greater12hrs_qf)) %>%
rename("healthboard" = "hbt") %>%
mutate(country = recode(country,
"S92000003" = "Scotland"))
hospital_location <- read_csv("../Dashboard_project/raw_data/wait_times_data/hospital_flagged20211216.csv") %>%
clean_names()
location_update_df <- left_join(clean_wait_times, hospital_location,
by = c("treatment_location" = "location"))
location_update_df <- location_update_df %>%
select(-c(hscpqf, caqf, int_zone_qf, data_zone_qf, based_on_postcode,
postcode, address_line, hb, ca, int_zone, data_zone))
scotland_area <- read_csv("../Dashboard_project/raw_data/wait_times_data/scotland_area.csv") %>% clean_names()
wait_times_clean <- left_join(location_update_df, scotland_area,
by = c("hscp" = "hscp")) %>%
select(-c(hscp, hscp_date_enacted, hscp_date_archived, hb, hb_name,
hb_date_enacted, hb_date_archived, country.y)) %>%
select(month, country.x, treatment_location, healthboard, hscp_name,
location_name, everything()) %>%
rename("country" = "country.x") %>%
mutate(month = ym(month),
month = format_ISO8601(month, precision = "ym")) %>%
rename("year_month" = "month")
wait_times_clean <- wait_times_clean %>%
mutate(year = ym(year_month),
year = year(year),
month = ym(year_month),
month = month(month, label = TRUE, abbr = FALSE)) %>%
# quarter = ym(year_month),
# quarter = yearquarter(quarter)) %>%
select(year_month, year, month, country:department_type, everything()) %>%
mutate(healthboard = recode(healthboard,
"S08000015" = "NHS Ayrshire and Arran",
"S08000016" = "NHS Borders",
"S08000017" = "NHS Dumfries and Galloway",
"S08000019" = "NHS Forth Valley",
"S08000020" = "NHS Grampian",
"S08000022" = "NHS Highland",
"S08000024" = "NHS Lothian",
"S08000025" = "NHS Orkney",
"S08000026" = "NHS Shetland",
"S08000028" = "NHS Western Isles",
"S08000029" = "NHS Fife",
"S08000030" = "NHS Tayside",
"S08000031" = "NHS Greater Glasgow and Clyde",
"S08000032" = "NHS Lanarkshire"))
wait_times_clean
geometry_data <- sf::st_read(here:here("../raw_data/Shape_data/SG_NHS_HealthBoards_2019.shp")) %>%
clean_names()
Error in sf::st_read(here:here("../raw_data/Shape_data/SG_NHS_HealthBoards_2019.shp")) :
object 'here' not found
wait_times_clean <- wait_times_clean %>%
mutate(percent_target_met = number_meeting_target_aggregate/number_of_attendances_aggregate,
percent_target_met_ep = number_meeting_target_episode/number_of_attendances_episode)
wait_times_clean
# percentage of attendance target met (aggregate)
wait_times_clean %>%
group_by(year, healthboard) %>%
summarise(n = mean(percent_target_met)) %>%
ggplot(aes(year, n, colour = healthboard, group = healthboard)) +
scale_y_continuous(labels=scales::percent) +
geom_line() +
theme_classic() +
labs(x = "Year", y = "Percentage", title = "Healthboard Attendance Target Met (Percentage)")
# percentage of attendance target met (episode)
wait_times_clean %>%
group_by(year, healthboard) %>%
summarise(n = mean(percent_target_met_ep)) %>%
ggplot(aes(year, n, colour = healthboard, group = healthboard)) +
scale_y_continuous(labels=scales::percent) +
geom_line() +
theme_classic() +
labs(x = "Year", y = "Percentage", title = "Healthboard Attendance Target Met (Percentage)")
wait_times_clean
write_csv(x = wait_times_clean, file = "../clean_data/wait_times_clean.csv")
write_csv(x = dropped_joined_waiting, file = "../clean_data/map_data_waiting_times.csv")
st_write(dropped_joined_waiting, here::here("../clean_data/map_data_waiting_t.geojson"), append = TRUE)
boxplot(wait_times_clean$attendance_greater8hrs ~ wait_times_clean$month)
ts_wait_time <- wait_times_clean %>%
mutate(year_month = yearmonth(x = year_month)) %>%
as_tsibble(key = c(healthboard, hscp_name, location_name), index = year_month)
ts_wait_time <- wait_times_clean %>%
select(year_month, number_meeting_target_aggregate)
wait_times_clean %>%
select(year_month, treatment_location, healthboard, hscp_name, location_name,
number_meeting_target_aggregate) %>%
mutate(year_month = yearmonth(x = year_month)) %>%
as_tsibble(key = c(healthboard, treatment_location, hscp_name, location_name), index = year_month)
tsib_wait_time <- ts_wait_time %>%
rowid_to_column(var = "id") %>%
mutate(year_month = yearmonth(year_month)) %>%
as_tsibble(index = year_month, key = id)
wait_tsib <- tsib_wait_time %>%
index_by(year_month) %>%
summarise(avg_target_met_agg = mean(number_meeting_target_aggregate))
wait_tsib %>%
autoplot(avg_target_met_agg)
## Rolling wait times
## doesnt work
rolling_wait <- ts_wait_time %>%
group_by(year_month) %>%
summarise(avg_meeting_target = mean(number_meeting_target_aggregate))
roll_wait <- rolling_wait %>%
mutate(temp_moving_avg = slide_dbl(
.x = avg_meeting_target,
.f = ~ mean(., na.rm = TRUE),
.before = 1000,
.after = 1000
)
)
roll_wait
ggplot(roll_wait) +
geom_line(aes(x = year_month, y = avg_meeting_target), colour = "grey") +
geom_line(aes(x = year_month, y = temp_moving_avg), colour = "red")
wait_tsib <- tsib_wait_time %>%
index_by(year_month) %>%
summarise(avg_target_met_agg = mean(number_meeting_target_aggregate))
week_fit <- wait_tsib %>%
model(
# snaive = SNAIVE(avg_target_met_agg ~ lag("year_month")),
# mean_model = MEAN(avg_target_met_agg),
arima = ARIMA(avg_target_met_agg)
)
forecast_week <- week_fit %>%
fabletools::forecast(h = 120)
forecast_week
forecast_week %>%
autoplot(wait_tsib, level = NULL) +
ggtitle("10 Year Forecast of NHS Targets Met") +
xlab("Year") +
ylab("Average Target Met") +
guides(colour = guide_legend(title = "Forecast")) +
theme_classic()
## Prophet prediction
wait_prophet <- wait_tsib %>%
mutate(ds = year_month,
y = avg_target_met_agg)
wait_prophet <- column_to_rownames(wait_prophet, var = "ds")
wait_prophet <- mutate(wait_prophet, ds = year_month)
prophet <- prophet(wait_prophet)
future <- make_future_dataframe(prophet, periods = 600)
forecast_p <- predict(prophet, future)
plot(prophet, forecast_p) +
xlab("Time") +
ylab("target_met_agg") +
labs(title = "Prophet forecast of Target Met Aggregate")
library(slider)
prophet
wait_tsib
## Look at subplots tommorrow - subseries/ggseason
## need to put an id into the main dataset to turn it into a tsibble, then can
## do one of these forecasts
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkodHNpYmJsZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHJuYXR1cmFsZWFydGgpCmxpYnJhcnkoanNvbmxpdGUpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShqYW5pdG9yKQpsaWJyYXJ5KHNwKQpgYGAKCmBgYHtyfQp3YWl0X3RpbWVzIDwtIHJlYWRfY3N2KCIuLi9EYXNoYm9hcmRfcHJvamVjdC9yYXdfZGF0YS93YWl0X3RpbWVzX2RhdGEvbW9udGhseV9hZV93YWl0aW5ndGltZXNfMjAyMjA5LmNzdiIpICU+JSBjbGVhbl9uYW1lcygpCmBgYAoKYGBge3J9CmNsZWFuX3dhaXRfdGltZXMgPC0gd2FpdF90aW1lcyAlPiUgCiAgc2VsZWN0KC1jKG51bWJlcl9vZl9hdHRlbmRhbmNlc19lcGlzb2RlX3FmLCBudW1iZXJfbWVldGluZ190YXJnZXRfZXBpc29kZV9xZiwKICAgICAgICAgICAgZGlzY2hhcmdlX2Rlc3RpbmF0aW9uX2FkbWlzc2lvbl90b19zYW1lX3FmLCBkaXNjaGFyZ2VfZGVzdGluYXRpb25fb3RoZXJfc3BlY2lhbHR5X3FmLAogICAgICAgICAgICBkaXNjaGFyZ2VfZGVzdGluYXRpb25fcmVzaWRlbmNlX3FmLCBkaXNjaGFyZ2VfZGVzdGluYXRpb25fdW5rbm93bl9xZiwKICAgICAgICAgICAgZGlzY2hhcmdlX2Rlc3RpbmF0aW9uX3RyYW5zZmVyX3FmLCBhdHRlbmRhbmNlX2dyZWF0ZXI4aHJzX3FmLAogICAgICAgICAgICBhdHRlbmRhbmNlX2dyZWF0ZXIxMmhyc19xZikpICU+JSAKICByZW5hbWUoImhlYWx0aGJvYXJkIiA9ICJoYnQiKSAlPiUgCiAgbXV0YXRlKGNvdW50cnkgPSByZWNvZGUoY291bnRyeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAiUzkyMDAwMDAzIiA9ICJTY290bGFuZCIpKQoKYGBgCgoKYGBge3J9Cmhvc3BpdGFsX2xvY2F0aW9uIDwtIHJlYWRfY3N2KCIuLi9EYXNoYm9hcmRfcHJvamVjdC9yYXdfZGF0YS93YWl0X3RpbWVzX2RhdGEvaG9zcGl0YWxfZmxhZ2dlZDIwMjExMjE2LmNzdiIpICU+JSAKICBjbGVhbl9uYW1lcygpCmBgYAoKCmBgYHtyfQpsb2NhdGlvbl91cGRhdGVfZGYgPC0gbGVmdF9qb2luKGNsZWFuX3dhaXRfdGltZXMsIGhvc3BpdGFsX2xvY2F0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoInRyZWF0bWVudF9sb2NhdGlvbiIgPSAibG9jYXRpb24iKSkKCmxvY2F0aW9uX3VwZGF0ZV9kZiA8LSBsb2NhdGlvbl91cGRhdGVfZGYgJT4lIAogIHNlbGVjdCgtYyhoc2NwcWYsIGNhcWYsIGludF96b25lX3FmLCBkYXRhX3pvbmVfcWYsIGJhc2VkX29uX3Bvc3Rjb2RlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3Rjb2RlLCBhZGRyZXNzX2xpbmUsIGhiLCBjYSwgaW50X3pvbmUsIGRhdGFfem9uZSkpCmBgYAoKYGBge3J9CnNjb3RsYW5kX2FyZWEgPC0gcmVhZF9jc3YoIi4uL0Rhc2hib2FyZF9wcm9qZWN0L3Jhd19kYXRhL3dhaXRfdGltZXNfZGF0YS9zY290bGFuZF9hcmVhLmNzdiIpICU+JSBjbGVhbl9uYW1lcygpCmBgYAoKYGBge3J9CndhaXRfdGltZXNfY2xlYW4gPC0gbGVmdF9qb2luKGxvY2F0aW9uX3VwZGF0ZV9kZiwgc2NvdGxhbmRfYXJlYSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiaHNjcCIgPSAiaHNjcCIpKSAlPiUgCiAgc2VsZWN0KC1jKGhzY3AsIGhzY3BfZGF0ZV9lbmFjdGVkLCBoc2NwX2RhdGVfYXJjaGl2ZWQsIGhiLCBoYl9uYW1lLCAKICAgICAgICAgICAgaGJfZGF0ZV9lbmFjdGVkLCBoYl9kYXRlX2FyY2hpdmVkLCBjb3VudHJ5LnkpKSAlPiUgCiAgc2VsZWN0KG1vbnRoLCBjb3VudHJ5LngsIHRyZWF0bWVudF9sb2NhdGlvbiwgaGVhbHRoYm9hcmQsIGhzY3BfbmFtZSwgCiAgICAgICAgIGxvY2F0aW9uX25hbWUsIGV2ZXJ5dGhpbmcoKSkgJT4lIAogIHJlbmFtZSgiY291bnRyeSIgPSAiY291bnRyeS54IikgJT4lIAogIG11dGF0ZShtb250aCA9IHltKG1vbnRoKSwKICAgICAgICAgbW9udGggPSBmb3JtYXRfSVNPODYwMShtb250aCwgcHJlY2lzaW9uID0gInltIikpICU+JSAKICByZW5hbWUoInllYXJfbW9udGgiID0gIm1vbnRoIikKYGBgCgpgYGB7cn0Kd2FpdF90aW1lc19jbGVhbiA8LSB3YWl0X3RpbWVzX2NsZWFuICU+JQogIG11dGF0ZSh5ZWFyID0geW0oeWVhcl9tb250aCksCiAgICAgICAgIHllYXIgPSB5ZWFyKHllYXIpLAogICAgICAgICBtb250aCA9IHltKHllYXJfbW9udGgpLAogICAgICAgICBtb250aCA9IG1vbnRoKG1vbnRoLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkpICU+JSAKICAgICAgICAgIyBxdWFydGVyID0geW0oeWVhcl9tb250aCksCiAgICAgICAgICMgcXVhcnRlciA9IHllYXJxdWFydGVyKHF1YXJ0ZXIpKSAlPiUgCiAgc2VsZWN0KHllYXJfbW9udGgsIHllYXIsIG1vbnRoLCBjb3VudHJ5OmRlcGFydG1lbnRfdHlwZSwgZXZlcnl0aGluZygpKSAlPiUgCiAgbXV0YXRlKGhlYWx0aGJvYXJkID0gcmVjb2RlKGhlYWx0aGJvYXJkLAogICAgICAgICAgICAgICAgICAgICAiUzA4MDAwMDE1IiA9ICJOSFMgQXlyc2hpcmUgYW5kIEFycmFuIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAxNiIgPSAiTkhTIEJvcmRlcnMiLAogICAgICAgICAgICAgICAgICAgICAiUzA4MDAwMDE3IiA9ICJOSFMgRHVtZnJpZXMgYW5kIEdhbGxvd2F5IiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAxOSIgPSAiTkhTIEZvcnRoIFZhbGxleSIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjAiID0gIk5IUyBHcmFtcGlhbiIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjIiID0gIk5IUyBIaWdobGFuZCIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjQiID0gIk5IUyBMb3RoaWFuIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAyNSIgPSAiTkhTIE9ya25leSIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjYiID0gIk5IUyBTaGV0bGFuZCIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjgiID0gIk5IUyBXZXN0ZXJuIElzbGVzIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAyOSIgPSAiTkhTIEZpZmUiLAogICAgICAgICAgICAgICAgICAgICAiUzA4MDAwMDMwIiA9ICJOSFMgVGF5c2lkZSIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMzEiID0gIk5IUyBHcmVhdGVyIEdsYXNnb3cgYW5kIENseWRlIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAzMiIgPSAiTkhTIExhbmFya3NoaXJlIikpCiAgCmBgYAoKYGBge3J9CndhaXRfdGltZXNfY2xlYW4KYGBgCgoKYGBge3J9Cmdlb21ldHJ5X2RhdGEgPC0gc2Y6OnN0X3JlYWQoaGVyZTo6aGVyZSgiLi4vRGF5IDUvd2FpdF90aW1lc19kYXRhL1NHX05IU19IZWFsdGhCb2FyZHNfMjAxOS5zaHAiKSkgJT4lCiAgY2xlYW5fbmFtZXMoKQoKZ2VvbWV0cnlfZGF0YSA8LSBzZjo6c3RfcmVhZChoZXJlOmhlcmUoIi4uL3Jhd19kYXRhL1NoYXBlX2RhdGEvU0dfTkhTX0hlYWx0aEJvYXJkc18yMDE5LnNocCIpKSAlPiUKICBjbGVhbl9uYW1lcygpCgpzaW1wbGVfZ2VvX2RhdGEgPC0gc3Rfc2ltcGxpZnkoZ2VvbWV0cnlfZGF0YSwgcHJlc2VydmVUb3BvbG9neSA9IEZBTFNFLCBkVG9sZXJhbmNlID0gMTAwMCkKc2ltcGxlX2dlb19kYXRhCgp1a2dyaWQgPC0gIitpbml0PWVwc2c6Mjc3MDAiCmxhdGxvbmcgPC0gIitpbml0PWVwc2c6NDMyNiIKCmxhdF9sb25nX2dlb19kYXRhIDwtIHN0X3RyYW5zZm9ybShzaW1wbGVfZ2VvX2RhdGEsIGNycyA9IGxhdGxvbmcpCgpsYXRfbG9uZ19nZW9fZGF0YQoKam9pbmVkX3dhaXRpbmcgPC0gIHdhaXRfdGltZXNfY2xlYW4gJT4lCiAgbGVmdF9qb2luKGxhdF9sb25nX2dlb19kYXRhLCBieSA9IGMoImhlYWx0aGJvYXJkIiA9ICJoYl9jb2RlIikpCgpqb2luZWRfd2FpdGluZyA8LSBqb2luZWRfd2FpdGluZyAlPiUgCiAgbXV0YXRlKGhlYWx0aGJvYXJkID0gcmVjb2RlKGhlYWx0aGJvYXJkLAogICAgICAgICAgICAgICAgICAgICAiUzA4MDAwMDE1IiA9ICJOSFMgQXlyc2hpcmUgYW5kIEFycmFuIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAxNiIgPSAiTkhTIEJvcmRlcnMiLAogICAgICAgICAgICAgICAgICAgICAiUzA4MDAwMDE3IiA9ICJOSFMgRHVtZnJpZXMgYW5kIEdhbGxvd2F5IiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAxOSIgPSAiTkhTIEZvcnRoIFZhbGxleSIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjAiID0gIk5IUyBHcmFtcGlhbiIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjIiID0gIk5IUyBIaWdobGFuZCIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjQiID0gIk5IUyBMb3RoaWFuIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAyNSIgPSAiTkhTIE9ya25leSIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjYiID0gIk5IUyBTaGV0bGFuZCIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMjgiID0gIk5IUyBXZXN0ZXJuIElzbGVzIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAyOSIgPSAiTkhTIEZpZmUiLAogICAgICAgICAgICAgICAgICAgICAiUzA4MDAwMDMwIiA9ICJOSFMgVGF5c2lkZSIsCiAgICAgICAgICAgICAgICAgICAgICJTMDgwMDAwMzEiID0gIk5IUyBHcmVhdGVyIEdsYXNnb3cgYW5kIENseWRlIiwKICAgICAgICAgICAgICAgICAgICAgIlMwODAwMDAzMiIgPSAiTkhTIExhbmFya3NoaXJlIikpCgpqb2luZWRfd2FpdGluZ1siZ2VvbWV0cnkiXSAlPiUgCiAgcHVsbCgpCgpkcm9wcGVkX2pvaW5lZF93YWl0aW5nIDwtIGpvaW5lZF93YWl0aW5nICU+JQogIGRyb3BfbmEoKQoKZHJvcHBlZF9qb2luZWRfd2FpdGluZyA8LSBzdF9hc19zZihkcm9wcGVkX2pvaW5lZF93YWl0aW5nKQoKZHJvcHBlZF9qb2luZWRfd2FpdGluZwoKc3RfZ2VvbWV0cnkoZHJvcHBlZF9qb2luZWRfd2FpdGluZykKCmRyb3BwZWRfam9pbmVkX3dhaXRpbmcgJT4lIAogIGdncGxvdChhZXMoZmlsbCA9IHBlcmNlbnRfdGFyZ2V0X21ldF9lcCkpICsKICBnZW9tX3NmKCkgKwogIHRoZW1lX21hcCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKIyBkYXRhIGZyYW1lIGZvciBwbG90dGluZyBnZW9tZXRyeSBwb2ludHMKCmRyb3BwZWRfam9pbmVkX3dhaXRpbmcgPC0gZHJvcHBlZF9qb2luZWRfd2FpdGluZyAlPiUgCiAgc2VsZWN0KHllYXJfbW9udGg6YXR0ZW5kYW5jZV9ncmVhdGVyMTJocnMsIGdlb21ldHJ5KSAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfdGFyZ2V0X21ldCA9IG51bWJlcl9tZWV0aW5nX3RhcmdldF9hZ2dyZWdhdGUvbnVtYmVyX29mX2F0dGVuZGFuY2VzX2FnZ3JlZ2F0ZSAqIDEwMCwKICAgICAgICAgcGVyY2VudF90YXJnZXRfbWV0X2VwID0gbnVtYmVyX21lZXRpbmdfdGFyZ2V0X2VwaXNvZGUvbnVtYmVyX29mX2F0dGVuZGFuY2VzX2VwaXNvZGUgKjEwMCkKCmRyb3BwZWRfam9pbmVkX3dhaXRpbmcKCm1hcF92YXJpYWJsZXMgPC0gZHJvcHBlZF9qb2luZWRfd2FpdGluZyAlPiUgc2VsZWN0KHBlcmNlbnRfdGFyZ2V0X21ldCwgcGVyY2VudF90YXJnZXRfbWV0X2VwKQogIApgYGAKCgoKYGBge3J9CndhaXRfdGltZXNfY2xlYW4gPC0gd2FpdF90aW1lc19jbGVhbiAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfdGFyZ2V0X21ldCA9IG51bWJlcl9tZWV0aW5nX3RhcmdldF9hZ2dyZWdhdGUvbnVtYmVyX29mX2F0dGVuZGFuY2VzX2FnZ3JlZ2F0ZSwKICAgICAgICAgcGVyY2VudF90YXJnZXRfbWV0X2VwID0gbnVtYmVyX21lZXRpbmdfdGFyZ2V0X2VwaXNvZGUvbnVtYmVyX29mX2F0dGVuZGFuY2VzX2VwaXNvZGUpCgp3YWl0X3RpbWVzX2NsZWFuCgojIHBlcmNlbnRhZ2Ugb2YgYXR0ZW5kYW5jZSB0YXJnZXQgbWV0IChhZ2dyZWdhdGUpCiAgCndhaXRfdGltZXNfY2xlYW4gJT4lICAgCiAgZ3JvdXBfYnkoeWVhciwgaGVhbHRoYm9hcmQpICU+JSAKICBzdW1tYXJpc2UobiA9IG1lYW4ocGVyY2VudF90YXJnZXRfbWV0KSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbiwgY29sb3VyID0gaGVhbHRoYm9hcmQsIGdyb3VwID0gaGVhbHRoYm9hcmQpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBnZW9tX2xpbmUoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHggPSAiWWVhciIsIHkgPSAiUGVyY2VudGFnZSIsIHRpdGxlID0gIkhlYWx0aGJvYXJkIEF0dGVuZGFuY2UgVGFyZ2V0IE1ldCAoUGVyY2VudGFnZSkiKQoKIyBwZXJjZW50YWdlIG9mIGF0dGVuZGFuY2UgdGFyZ2V0IG1ldCAoZXBpc29kZSkKCndhaXRfdGltZXNfY2xlYW4gJT4lICAgCiAgZ3JvdXBfYnkoeWVhciwgaGVhbHRoYm9hcmQpICU+JSAKICBzdW1tYXJpc2UobiA9IG1lYW4ocGVyY2VudF90YXJnZXRfbWV0X2VwKSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbiwgY29sb3VyID0gaGVhbHRoYm9hcmQsIGdyb3VwID0gaGVhbHRoYm9hcmQpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBnZW9tX2xpbmUoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHggPSAiWWVhciIsIHkgPSAiUGVyY2VudGFnZSIsIHRpdGxlID0gIkhlYWx0aGJvYXJkIEF0dGVuZGFuY2UgVGFyZ2V0IE1ldCAoUGVyY2VudGFnZSkiKQoKd2FpdF90aW1lc19jbGVhbgogIApgYGAKCmBgYHtyfQp3cml0ZV9jc3YoeCA9IHdhaXRfdGltZXNfY2xlYW4sIGZpbGUgPSAiLi4vY2xlYW5fZGF0YS93YWl0X3RpbWVzX2NsZWFuLmNzdiIpCgp3cml0ZV9jc3YoeCA9IGRyb3BwZWRfam9pbmVkX3dhaXRpbmcsIGZpbGUgPSAiLi4vY2xlYW5fZGF0YS9tYXBfZGF0YV93YWl0aW5nX3RpbWVzLmNzdiIpCmBgYAoKYGBge3J9CnN0X3dyaXRlKGRyb3BwZWRfam9pbmVkX3dhaXRpbmcsIGhlcmU6OmhlcmUoIi4uL2NsZWFuX2RhdGEvbWFwX2RhdGFfd2FpdGluZ190Lmdlb2pzb24iKSwgYXBwZW5kID0gVFJVRSkKYGBgCgoKCgpgYGB7cn0KZHJvcHBlZF9qb2luZWRfd2FpdGluZwpgYGAKCmBgYHtyfQpib3hwbG90KHdhaXRfdGltZXNfY2xlYW4kYXR0ZW5kYW5jZV9ncmVhdGVyOGhycyB+IHdhaXRfdGltZXNfY2xlYW4kbW9udGgpCmBgYAoKYGBge3J9CnRzX3dhaXRfdGltZSA8LSB3YWl0X3RpbWVzX2NsZWFuICU+JSAKICBtdXRhdGUoeWVhcl9tb250aCA9IHllYXJtb250aCh4ID0geWVhcl9tb250aCkpICU+JSAKICBhc190c2liYmxlKGtleSA9IGMoaGVhbHRoYm9hcmQsIGhzY3BfbmFtZSwgbG9jYXRpb25fbmFtZSksIGluZGV4ID0geWVhcl9tb250aCkKCnRzX3dhaXRfdGltZSA8LSB3YWl0X3RpbWVzX2NsZWFuICU+JQogIHNlbGVjdCh5ZWFyX21vbnRoLCBudW1iZXJfbWVldGluZ190YXJnZXRfYWdncmVnYXRlKQoKd2FpdF90aW1lc19jbGVhbiAlPiUgCiAgc2VsZWN0KHllYXJfbW9udGgsIHRyZWF0bWVudF9sb2NhdGlvbiwgaGVhbHRoYm9hcmQsIGhzY3BfbmFtZSwgbG9jYXRpb25fbmFtZSwKICAgICAgICAgbnVtYmVyX21lZXRpbmdfdGFyZ2V0X2FnZ3JlZ2F0ZSkgJT4lIAogIG11dGF0ZSh5ZWFyX21vbnRoID0geWVhcm1vbnRoKHggPSB5ZWFyX21vbnRoKSkgJT4lIAogIGFzX3RzaWJibGUoa2V5ID0gYyhoZWFsdGhib2FyZCwgdHJlYXRtZW50X2xvY2F0aW9uLCBoc2NwX25hbWUsIGxvY2F0aW9uX25hbWUpLCBpbmRleCA9IHllYXJfbW9udGgpCgp0c2liX3dhaXRfdGltZSA8LSB0c193YWl0X3RpbWUgJT4lIAogIHJvd2lkX3RvX2NvbHVtbih2YXIgPSAiaWQiKSAlPiUgCiAgbXV0YXRlKHllYXJfbW9udGggPSB5ZWFybW9udGgoeWVhcl9tb250aCkpICU+JSAKICBhc190c2liYmxlKGluZGV4ID0geWVhcl9tb250aCwga2V5ID0gaWQpCgoKCndhaXRfdHNpYiA8LSB0c2liX3dhaXRfdGltZSAlPiUgCiAgaW5kZXhfYnkoeWVhcl9tb250aCkgJT4lIAogIHN1bW1hcmlzZShhdmdfdGFyZ2V0X21ldF9hZ2cgPSBtZWFuKG51bWJlcl9tZWV0aW5nX3RhcmdldF9hZ2dyZWdhdGUpKQoKd2FpdF90c2liICU+JSAKICBhdXRvcGxvdChhdmdfdGFyZ2V0X21ldF9hZ2cpIAoKIyMgUm9sbGluZyB3YWl0IHRpbWVzIAoKIyMgZG9lc250IHdvcmsgCgpyb2xsaW5nX3dhaXQgPC0gdHNfd2FpdF90aW1lICU+JSAKICBncm91cF9ieSh5ZWFyX21vbnRoKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19tZWV0aW5nX3RhcmdldCA9IG1lYW4obnVtYmVyX21lZXRpbmdfdGFyZ2V0X2FnZ3JlZ2F0ZSkpCgpyb2xsX3dhaXQgPC0gcm9sbGluZ193YWl0ICU+JSAKICBtdXRhdGUodGVtcF9tb3ZpbmdfYXZnID0gc2xpZGVfZGJsKAogICAgLnggPSBhdmdfbWVldGluZ190YXJnZXQsIAogICAgLmYgPSB+IG1lYW4oLiwgbmEucm0gPSBUUlVFKSwKICAgIC5iZWZvcmUgPSAxMDAwLAogICAgLmFmdGVyID0gMTAwMAogICkKICApCgpyb2xsX3dhaXQKCmdncGxvdChyb2xsX3dhaXQpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0geWVhcl9tb250aCwgeSA9IGF2Z19tZWV0aW5nX3RhcmdldCksIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyX21vbnRoLCB5ID0gdGVtcF9tb3ZpbmdfYXZnKSwgY29sb3VyID0gInJlZCIpCiAgCiAgCmBgYAoKYGBge3J9CndhaXRfdHNpYiA8LSB0c2liX3dhaXRfdGltZSAlPiUgCiAgaW5kZXhfYnkoeWVhcl9tb250aCkgJT4lIAogIHN1bW1hcmlzZShhdmdfdGFyZ2V0X21ldF9hZ2cgPSBtZWFuKG51bWJlcl9tZWV0aW5nX3RhcmdldF9hZ2dyZWdhdGUpKQoKd2Vla19maXQgPC0gd2FpdF90c2liICU+JSAKICBtb2RlbCgKICAgICMgc25haXZlID0gU05BSVZFKGF2Z190YXJnZXRfbWV0X2FnZyB+IGxhZygieWVhcl9tb250aCIpKSwKICAgICMgbWVhbl9tb2RlbCA9IE1FQU4oYXZnX3RhcmdldF9tZXRfYWdnKSwKICAgIGFyaW1hID0gQVJJTUEoYXZnX3RhcmdldF9tZXRfYWdnKQogICkKCmZvcmVjYXN0X3dlZWsgPC0gd2Vla19maXQgJT4lIAogIGZhYmxldG9vbHM6OmZvcmVjYXN0KGggPSAxMjApCmZvcmVjYXN0X3dlZWsKCmZvcmVjYXN0X3dlZWsgJT4lCiAgYXV0b3Bsb3Qod2FpdF90c2liLCBsZXZlbCA9IE5VTEwpICsKICBnZ3RpdGxlKCIxMCBZZWFyIEZvcmVjYXN0IG9mIE5IUyBUYXJnZXRzIE1ldCIpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIkF2ZXJhZ2UgVGFyZ2V0IE1ldCIpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkZvcmVjYXN0IikpICsKICB0aGVtZV9jbGFzc2ljKCkKCiMjIFByb3BoZXQgcHJlZGljdGlvbgoKICAgICAgd2FpdF9wcm9waGV0IDwtIHdhaXRfdHNpYiAlPiUgCiAgICAgICAgbXV0YXRlKGRzID0geWVhcl9tb250aCwKICAgICAgICAgICAgICAgeSA9IGF2Z190YXJnZXRfbWV0X2FnZykKICAgICAgCiAgICAgIHdhaXRfcHJvcGhldCA8LSBjb2x1bW5fdG9fcm93bmFtZXMod2FpdF9wcm9waGV0LCB2YXIgPSAiZHMiKSAKICAgICAgCiAgICAgIHdhaXRfcHJvcGhldCA8LSAgbXV0YXRlKHdhaXRfcHJvcGhldCwgZHMgPSB5ZWFyX21vbnRoKQogICAgICAKICAgICAgcHJvcGhldCA8LSBwcm9waGV0KHdhaXRfcHJvcGhldCkKICAgICAgCiAgICAgIGZ1dHVyZSA8LSBtYWtlX2Z1dHVyZV9kYXRhZnJhbWUocHJvcGhldCwgcGVyaW9kcyA9IDYwMCkKICAgICAgCiAgICAgIGZvcmVjYXN0X3AgPC0gcHJlZGljdChwcm9waGV0LCBmdXR1cmUpCiAgICAgIAogICAgICBwbG90KHByb3BoZXQsIGZvcmVjYXN0X3ApICsKICAgICAgICB4bGFiKCJUaW1lIikgKwogICAgICAgIHlsYWIoInRhcmdldF9tZXRfYWdnIikgKwogICAgICAgIGxhYnModGl0bGUgPSAiUHJvcGhldCBmb3JlY2FzdCBvZiBUYXJnZXQgTWV0IEFnZ3JlZ2F0ZSIpCiAgICAgICAgCiAgICAgIApsaWJyYXJ5KHNsaWRlcikKICAgICAgCgpwcm9waGV0Cgp3YWl0X3RzaWIKCgojIyBMb29rIGF0IHN1YnBsb3RzIHRvbW1vcnJvdyAtIHN1YnNlcmllcy9nZ3NlYXNvbiAKCiMjIG5lZWQgdG8gcHV0IGFuIGlkIGludG8gdGhlIG1haW4gZGF0YXNldCB0byB0dXJuIGl0IGludG8gYSB0c2liYmxlLCB0aGVuIGNhbgojIyBkbyBvbmUgb2YgdGhlc2UgZm9yZWNhc3RzCgpgYGAKCmBgYHtyfQp0c2liX3dhaXRfdGltZQpgYGAKCg==